package com.open.basic.job;

import com.open.basic.event.EventPublisherFactory;
import com.open.basic.thread.ThreadPoolUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.support.CronExpression;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * @author: system
 * @Date: 2024/10/17 下午4:19
 * @Version: V1.0
 * @description: | 基础调度任务
 */

public abstract class BasicJobRunnable implements Runnable {

    private static final Logger log = LoggerFactory.getLogger(BasicJobRunnable.class);

    private static final ThreadPoolExecutor EXECUTOR = ThreadPoolUtil.getNewThreadPool("codex-schedule-", 20);

    private BasicTask basicTask;

    public BasicJobRunnable(BasicTask basicTask) {
        this.basicTask = basicTask;
    }


    @Override
    public void run() {
        EXECUTOR.execute(() -> {
            try {
                LocalDateTime now = LocalDateTime.now();
                log.info("开始执行调度任务：{} 参数：[{}]", basicTask.getTaskName(), basicTask.getParam());
                this.basicTask.setExecutionStartTime(LocalDateTime.now());
                this.basicTask.setStatus(BasicTask.STATUS_RUNNING);
                if (basicTask.getExecuteCount() == 0) {
                    basicTask.setFirstRunTime(now);
                }
                this.basicTask.setLastRunTime(now);
                this.basicTask.setExecuteCount(basicTask.getExecuteCount() + 1);
                JobEvent event = new JobEvent(this, basicTask);
                EventPublisherFactory.publishEvent(event);
                this.execute(basicTask.getParam());
                this.basicTask.setStatus(BasicTask.STATUS_SUCCESS);
            } catch (Exception e) {
                this.basicTask.setStatus(BasicTask.STATUS_FAIL);
                this.basicTask.setFailureMessage(e.getMessage());
                log.error("调度任务执行失败", e);
            } finally {
                LocalDateTime now = LocalDateTime.now();
                this.basicTask.setExecutionEndTime(now);
                // 两个时间间隔
                long duration = Duration.between(basicTask.getExecutionStartTime(), basicTask.getExecutionEndTime()).toMillis();
                this.basicTask.setTaskDuration(duration);
                CronExpression parse = CronExpression.parse(basicTask.getCron());
                LocalDateTime next = parse.next(LocalDateTime.now());
                this.basicTask.setNextExecutionTime(next);
                JobEvent event = new JobEvent(this, basicTask);
                EventPublisherFactory.publishEvent(event);
            }
            log.info("调度任务执行完成，任务名：{}", basicTask.getTaskName());
        });
    }

    public BasicTask getBasicTask() {
        return basicTask;
    }

    /**
     * 执行任务，记录执行日志
     *
     * @param param
     */
    protected abstract void execute(String param) throws InterruptedException;
}
